#!/usr/bin/env python3.10
# -*- encoding: utf-8 -*-
"""
@File    :   article.py
@Time    :   2024/01/03 20:01:01
@Author  :   windstarry 
@Version :   1.0
"""
# here put the import lib
from ninja.pagination import paginate
from ninja import Router, Field, Schema, ModelSchema, Query, Form,UploadedFile
from typing import Union, List, Optional, Any
from django.db import transaction
from django.forms import model_to_dict
from pydantic import validator

from article.models import Article
from utils.response import R
from utils.crud import create, delete, retrieve, update
from utils.auth import BaseFilters, MyPagination, get_user_info_from_token
from utils.tools import custom_model_to_dict

router = Router()


class Filters(BaseFilters):
    title: str = Field(None, alias="title")
    content: str = Field(None, alias="content")
    cate: str = Field(None, alias="cate_id")
    cover_img: str = Field(None, alias="cover_img")
    status: str = Field(None, alias="status")
    id: str = Field(None, alias="id")


class SchemaIn(ModelSchema):
    cate_id: int = Field(..., description="分类id")
    status: str = Field(..., description="发布状态")
    # 文章封面为''或者binary
    # cover_img:Union[str,UploadedFile]= Field(None, description="文章封面")
    cover_img: UploadedFile|None = None
    class Config:
        model = Article
        model_fields = [
            "title",
            "content",
        ]


class UpdateSchema(SchemaIn):
    id: int = Field(..., description="文章id")


class SchemaOut(ModelSchema):
    status: Optional[int] = Field(..., description="发布状态")
    cate: Optional[int] = Field(..., description="分类id")

    class Config:
        model = Article
        model_fields = [
            "id",
            "title",
            "content",
            "cover_img",
            "update_datetime",
        ]
        
    

STATUS_CHOICES = (
    (0, "草稿"),
    (1, "已发布"),
)


class ArticleInfo(Schema):
    id: int = Field(..., description="文章id")
    title: str = Field(..., description="文章标题")
    content: str = Field(..., description="文章内容")
    cover_img: str = Field(..., description="文章封面")
    status: str = Field(..., description="发布状态")
    # 分类id
    cate_id: int = Field(..., description="分类id")
    cate_name: str = Field(..., description="分类名称")
    # 创建者
    author_id: int = Field(..., description="作者id")
    username: str = Field(..., description="作者")
    nickname: str = Field(..., description="作者昵称")


# 获取文章列表
@router.get("/list", summary="文章列表", response=Union[SchemaOut, R])
def get_article_list(request, filters: Filters = Query(...)):
    articles = retrieve(request, Article, filters)
    data = {
        "total": articles.count(),
        "items": [SchemaOut(**custom_model_to_dict(article)) for article in articles],
    }
    return R.ok(data=data, msg="获取文章列表成功")


# 增加文章
@router.post("/add", summary="增加文章", response=Union[SchemaOut, R])
def create_article(request, form: SchemaIn = Form(...)):
    try:
        with transaction.atomic():
            data = form.dict()
            data.pop("cover_img")
            # 根据dict_data中status字段，结合STATUS_CHOICES判断status
            data["status"] = 1 if data["status"] == "已发布" else 0
            article = create(request, data, Article)
            cover_img = request.FILES.get("cover_img")
            if cover_img:
                cover_img_format = cover_img.name.split('.')[-1]
                # 修改名称,上传图片
                article.cover_img.save(f'article_{article.id}.{cover_img_format}', cover_img)
            article = SchemaOut(**model_to_dict(article))
            return R.ok(data=article, msg="文章添加成功")
    except Exception as e:
        return R.fail(msg="文章添加失败")
    
   


# 删除文章
@router.delete("/del/{id}", summary="删除文章", response=R)
def delete_article(request, id: int):
    try:
        # 从请求中获取用户信息
        request_user = get_user_info_from_token(request)
        # 验证该用户是否已有该文章
        if not Article.objects.filter(id=id, creator_id=request_user["id"]).exists():
            return R.fail(msg="无权限删除该文章")
        delete(id, Article)
        return R.ok(msg="删除成功")
    except Exception as e:
        return R.fail(msg="删除失败")


# 修改文章
@router.post("/info", summary="修改文章", response=R)
def update_article(request,paylaod: UpdateSchema = Form(...)):
    user_info = get_user_info_from_token(request)
    from django.shortcuts import get_object_or_404
    try:
        with transaction.atomic():
            data = paylaod.dict()
            data.pop("cover_img")
            # 根据ata中status字段，结合STATUS_CHOICES判断status
            data["status"] = 1 if data["status"] == "已发布" else 0
            # 更新时默认添加修改人
            data["modifier"] = user_info["username"]
            article  = get_object_or_404(Article, id=data["id"], creator_id=user_info["id"])
            article_img = article.cover_img.name.split('/')[-1]
            cover_img = request.FILES.get("cover_img")
            # 判断图片是否一样
            if cover_img and article_img != cover_img.name:
                cover_img_format = cover_img.name.split('.')[-1]
                article.cover_img.save(f'article_{article.id}.{cover_img_format}', cover_img)
            for attr, value in data.items():
                setattr(article, attr, value)
            article.save()
            return R.ok(msg="文章修改成功")
    except Exception as e:
        return R.fail(msg="文章修改失败")
    


# 获取文章详情
@router.get("/info/{id}", summary="获取文章详情", response=Union[ArticleInfo, R])
def get_article_info(request, id: int, filters: Filters = Query(...)):
    # 获取文章信息的视图函数
    # 参数:
    #   - request: 请求对象
    #   - id: 文章ID
    #   - filters: 筛选条件，默认为*(...)

    # 将id赋值给筛选条件对象
    filters.id = id
    # 通过筛选条件获取文章
    article = retrieve(request, Article, filters)
    # 如果文章不存在，则返回请求失败响应
    if not article:
        return R.fail(msg="文章不存在")
    # 创建文章信息对象
    data = ArticleInfo(
        id=article[0].id,  # 文章ID
        title=article[0].title,  # 文章标题
        content=article[0].content,  # 文章内容
        cover_img=article[0].cover_img,  # 文章封面图片
        # 通过status判断文章状态
        status=STATUS_CHOICES[article[0].status][1],
        cate_id=article[0].cate.id,  # 文章分类ID
        cate_name=article[0].cate.cate_name,  # 文章分类名称
        author_id=article[0].creator.id,  # 作者ID
        username=article[0].creator.username,  # 作者用户名
        nickname=article[0].creator.nickname,  # 作者昵称
    )
    # 返回请求成功响应，包含文章信息
    return R.ok(data=data, msg="获取文章详情成功")
